﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using DHJ.Cost.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DHJ.Cost.CostAccounting
{
    public class BatchCostManager : DomainService, IBatchCostManager
    {
        private readonly IRepository<AllocRel, Guid> _allocRelRepository;
        private readonly IRepository<Batch, string> _batchRepository;

        public BatchCostManager(IRepository<Batch, string> batchRepository,
            IRepository<AllocRel, Guid> allocRelRepository)
        {
            _batchRepository = batchRepository;
            _allocRelRepository = allocRelRepository;
        }

        public IQueryable<AllocRel> BatchCosts => _allocRelRepository.GetAll();

        /// <summary>
        ///     获得一个条码/数量对应的成本项，采用递归的方式包含父条码成本项。
        ///     不包含组成部件的成本。
        /// </summary>
        public async Task<List<AllocRel>> GetCostListAsync(IBatchIdentifier identifier)
        {
            //当前条码相关的成本项
            var costList = await GetSelfCostListAsync(identifier);

            //添加父条码相关的成本项
            var parentIdentifier = (await _batchRepository.GetAll().SingleAsync(b => b.Id == identifier.BatchId))?.ParentIdentifier();
            if (parentIdentifier == null) return costList; // Break Recursive

            var parentCostList = await GetCostListAsync(parentIdentifier);
            costList.AddRange(parentCostList);

            return costList;
        }

        public IQueryable<AllocRel> GetCosts(IBatchIdentifier identifier)
        {
            //当前条码相关的成本项
            var costs = GetSelfCosts(identifier);

            //添加父条码相关的成本项
            var parentIdentifier = _batchRepository.GetAll().Single(b => b.Id == identifier.BatchId).ParentIdentifier();
            if (parentIdentifier == null) return costs; // Break Recursive

            var parentCosts = GetCosts(parentIdentifier);
            costs = costs.Concat(parentCosts);

            return costs;
        }

        /// <summary>
        ///     获得一个条码/数量对应的成本项，不含父条码的成本项。
        /// </summary>
        private async Task<List<AllocRel>> GetSelfCostListAsync(IBatchIdentifier identifier)
        {
            return await _allocRelRepository.GetAll().Include(r => r.ActualCost)
                .Where(r => r.BatchId == identifier.BatchId)
                .Where(r => r.Quantity >= identifier.Quantity)
                .OrderByDescending(r => r.ActualCost.Time)
                .ToListAsync();
        }

        private IQueryable<AllocRel> GetSelfCosts(IBatchIdentifier identifier)
        {
            return _allocRelRepository.GetAll().Include(r => r.ActualCost)
                .Where(r => r.BatchId == identifier.BatchId)
                .Where(r => r.Quantity >= identifier.Quantity)
                .OrderByDescending(r => r.ActualCost.Time);
        }
    }
}